﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using UnitShared;

namespace tactics
{
    using Coord = Utility.Pair<int, int>;

    class DeploymentManager
    {
        public static void InitializeEverythingAtRandom(List<Player> players, List<UnitTemplate> units, TerrainMap terrainMap)
        {
            Random r = new Random();
            FillPlayerTeamsAtRandom(players, units);

            foreach (Player p in players)
            {
                var zone = FindSuitableDeploymentZone(p, terrainMap, r);
                var picked = new List<int>();

                foreach (var unit in p.Units)
                {
                    int max = zone.Count;
                    bool found = false;

                    while (!found)
                    {
                        int test = r.Next(max);
                        if (!picked.Contains(test))
                        {
                            unit.Move(zone[test].First, zone[test].Second, true);
                            picked.Add(test);
                            zone.RemoveAt(test);
                            found = true;
                        }
                    }
                }
            }
        }

        private static List<Coord> FindSuitableDeploymentZone(Player p, TerrainMap terrainMap, Random r)
        {
            var zone = new List<Coord>();

            bool found = false;
            int width = 5;
            int height = 3;

            while (!found)
            {
                found = true;
                int zx = r.Next(terrainMap.Width - width);
                int zy = r.Next(terrainMap.Height - height);
                
                zone = new List<Coord>();

                for (int y = zy; y < zy + height; ++y)
                {
                    for (int x = zx; x < zx + width; ++x)
                    {
                        TerrainRule rule = terrainMap.GetTypeAt(x, y);
                        if (rule == TerrainRule.Impassable  ||
                            rule == TerrainRule.Blocked     ||
                            rule == TerrainRule.Wall        ||
                            terrainMap.GetPlayerAt(x, y) != -1)
                            found = false;
                        else
                            zone.Add(new Coord(x, y));
                    }
                }
            }

            return zone;
        }

        private static void FillPlayerTeamsAtRandom(List<Player> players, List<UnitTemplate> units)
        {
            Random r = new Random();

            foreach (Player p in players)
            {
                int points = p.Points;

                while (PlayerCanAffordUnit(p, units))
                {
                    var selectable = from u in units
                                     where u.PointCost <= p.Points
                                     select u;

                    p.AddUnit(new Unit(selectable.ElementAt(r.Next(0, selectable.Count())).Clone()));
                }
            }
        }

        private static bool PlayerCanAffordUnit(Player p, List<UnitTemplate> units)
        {
            foreach (UnitTemplate u in units)
                if (p.Points - u.PointCost >= 0)
                    return true;

            return false;
        }
    }
}
